//
//  DXMLJamObject.m
//  DerbyStatter
//
//  Created by glenn andreas on 1/29/14.
//  Copyright (c) 2014 glenn andreas. All rights reserved.
//

#import "DXMLJamObject.h"
#import "DXMLPeriodObject.h"
#import "DXMLSkaterEventObject.h"
#import "DXMLTeamObject.h"
#import "DXMLPersonObject.h"
#import "DXMLTimeStamp.h"
#import "DXMLRuleSetObject.h"
#import "DXMLBoutObject.h"

@implementation DXMLJamObject
DXMLINTATTR(number, Number)

- (DXMLPeriodObject *) period
{
    return [self enclosingParentOfClass:[DXMLPeriodObject class]];
}

- (NSInteger) numberOfChildrenOfClass: (Class) cls team: (DXMLTeamObject *) team;
{
    __block NSInteger total = 0;
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        total++;
    } ofClass:cls team: team];
    return total;
}
- (id) childOfClass: (Class) cls atIndex: (NSInteger) index  team: (DXMLTeamObject *) team;
{
    __block DXMLEventObject *retval = nil;
    __block NSInteger total = 0;
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        if (total == index) {
            retval = child;
            *stop = YES;
        }
        total++;
    } ofClass:cls team: team];
    return retval;
}
- (id) childOfClass:(Class)cls atIndex:(NSInteger)index team: (DXMLTeamObject *) team source:(DXMLEventSource)source
{
    __block DXMLEventObject *retval = nil;
    __block NSInteger total = 0;
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        if (total == index) {
            retval = child;
            *stop = YES;
        }
        total++;
    } ofClass:cls team: team];
    if (!retval) {
        while (total != index+1) {
            retval = [[cls alloc] init];
            [self addChild:retval];
            [retval setSource:source];
            [(DXMLPassObject *)retval setTeam: team];
            total++;
        }
    }
    return retval;
}
- (void) enumerateChildren: (void (^)(DXMLEventObject *child, BOOL *stop)) block ofClass: (Class) cls  team: (DXMLTeamObject *) team;
{
    for (DXMLEventObject *child in self.children) {
        if ([child isKindOfClass:cls] && [[(DXMLPassObject *)child team] isEqual: team]) {
            BOOL stop = NO;
            block(child,&stop);
            if (stop)
                break;
        }
    }
}


- (NSInteger) numberOfChildrenOfClass: (Class) cls person: (DXMLPersonObject *) person;
{
    __block NSInteger total = 0;
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        total++;
    } ofClass:cls person:person];
    return total;
}
- (id) childOfClass: (Class) cls atIndex: (NSInteger) index  person: (DXMLPersonObject *) person;
{
    __block DXMLEventObject *retval = nil;
    __block NSInteger total = 0;
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        if (total == index) {
            retval = child;
            *stop = YES;
        }
        total++;
    } ofClass:cls person:person];
    return retval;
}
- (id) childOfClass: (Class) cls atIndex: (NSInteger) index  person: (DXMLPersonObject *) person source: (DXMLEventSource) source;
{
    __block DXMLEventObject *retval = nil;
    __block NSInteger total = 0;
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        if (total == index) {
            retval = child;
            *stop = YES;
        }
        total++;
    } ofClass:cls person:person];
    if (!retval) {
        while (total != index+1) {
            retval = [[cls alloc] init];
            [self addChild:retval];
            [retval setSource:source];
            [(DXMLPassObject *)retval setSkater:person];
            total++;
        }
    }
    return retval;
}
- (void) enumerateChildren: (void (^)(DXMLEventObject *child, BOOL *stop)) block ofClass: (Class) cls  person: (DXMLPersonObject *) person;
{
    for (DXMLEventObject *child in self.children) {
        if ([child isKindOfClass:cls] && [[(DXMLPassObject *)child skater] isEqual: person]) {
            BOOL stop = NO;
            block(child,&stop);
            if (stop)
                break;
        }
    }
}



- (NSInteger) numberOfPasses:(DXMLTeamObject *)team;
{
    return [self numberOfChildrenOfClass:[DXMLPassObject class]team:team];
}
- (id) passAtIndex: (NSInteger) index team: (DXMLTeamObject *) team
{
    return [self childOfClass:[DXMLPassObject class] atIndex:index team:team];
}
- (id) passAtIndex: (NSInteger) index team: (DXMLTeamObject *) team source: (DXMLEventSource) source
{
    return [self childOfClass:[DXMLPassObject class] atIndex:index team:team source: source];
}
- (void) enumeratePasses: (void (^)(DXMLPassObject *child, BOOL *stop)) block team: (DXMLTeamObject *) team
{
    [self enumerateChildren:(void (^)(DXMLEventObject *child, BOOL *stop))block ofClass:[DXMLPassObject class] team:team];
}
- (NSInteger) score:(DXMLTeamObject *)team
{
    __block NSInteger retval =0;
    [self enumeratePasses:^(DXMLPassObject *child, BOOL *stop) {
        if (child.score != NSNotFound)
            retval += child.score;
    } team:team];
    return retval;
}
- (NSInteger) startingScore: (DXMLTeamObject *) team;
{
    DXMLPeriodObject *period = self.period;
    DXMLBoutObject *bout = period.bout;
    NSInteger retval = 0;
    if (period == bout.secondPeriod) {
        retval = [bout.firstPeriod periodTotalForTeam:team upToJam:9999];
    }
    return retval + [period periodTotalForTeam:team upToJam:self.number - 1];
}
- (BOOL) lead: (DXMLTeamObject *) team
{
    return [self numberOfChildrenOfClass:[DXMLLeadObject class] team:team] != 0;
}
- (BOOL) lostLead: (DXMLTeamObject *) team
{
    return [self numberOfChildrenOfClass:[DXMLLostLeadObject class] team:team] != 0;
}
- (BOOL) call: (DXMLTeamObject *) team
{
    return [self numberOfChildrenOfClass:[DXMLCallObject class] team:team] != 0;
}
- (BOOL) hasStarPass: (DXMLTeamObject *) team
{
    return [self numberOfChildrenOfClass:[DXMLStarPassObject class] team:team] != 0;
}

- (BOOL) injury
{
    return [self numberOfChildrenOfClass:[DXMLInjuryObject class] ] != 0;
}
- (BOOL) noPass: (DXMLTeamObject *) team
{
#ifdef nomore
    DXMLPassObject *pass = [self passAtIndex:2-1 team:team]; //
    if (!pass)
        return YES;
    return NO;
#else
    // we now have explicit "no pass"
    DXMLPassObject *pass = [self passAtIndex:2-1 team:team]; //
    if (pass) return NO; // pass 2 exists
    pass = [self passAtIndex:1-1 team:team]; // check to see if pass 1 exists
    return pass.completed;
#endif
}
- (DXMLPersonObject *) jammer: (DXMLTeamObject *) team;
{
    __block DXMLPersonObject *retval = nil;
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        DXMLLineUpObject *lu = (DXMLLineUpObject *)child;
        if (lu.skater) {
            if ([lu.position isEqualToString:DXMLLineUpPositionJammer]) {
                retval = lu.skater;
            }
        }
    } ofClass:[DXMLLineUpObject class] team:team];
    return retval;
}
- (NSTimeInterval) duration;
{
    if (!self.timestamp)
        return 0;
    NSTimeInterval start = self.timestamp.date.timeIntervalSinceReferenceDate;
    __block NSTimeInterval end = start;
    DXMLRuleSetObject *rules = self.period.bout.ruleSet;
    if (rules)
        end = start + rules.jam;
    else
        end = start + 120; // 2 minutes hard code

    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        end = MIN(end, child.timestamp.date.timeIntervalSinceReferenceDate);
    } ofClass:[DXMLCallObject class]];
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        end = MIN(end, child.timestamp.date.timeIntervalSinceReferenceDate);
    } ofClass:[DXMLInjuryObject class]];
    return end - start;
}
- (NSDictionary *) lineupForTeam: (DXMLTeamObject *) team; // uses DXMLLineupPositionObject keys, with blocker returning an array
{
    __block NSMutableDictionary *retval = [NSMutableDictionary dictionary];
    [self enumerateChildren:^(DXMLEventObject *child, BOOL *stop) {
        DXMLLineUpObject *lu = (DXMLLineUpObject *)child;
        if (lu.skater) {
            if ([lu.position isEqualToString:DXMLLineUpPositionBlocker]) {
                NSMutableArray *blockers = [retval objectForKey:lu.position];
                if (!blockers) {
                    blockers = [NSMutableArray array];
                    [retval setObject:blockers forKey:DXMLLineUpPositionBlocker];
                }
                [blockers addObject:lu.skater];
            } else {
                if ([retval objectForKey:lu.position]) {
                    // this shouldn't happen - we already have a position...
                }
                [retval setObject:lu.skater forKey:lu.position];
            }
        }
    } ofClass:[DXMLLineUpObject class] team:team];
    return retval;
}


@end
